using System;
using System.Collections.Generic;
using System.Text;

namespace Weazel.Microblaze.Simulator.Engine
{
    public abstract class Transaction
    {
        public enum TransactionType
        {
            Write,
            Read
        }

        public enum TransactionStatus
        {
            Unknown,
            Complete,
            Pending
        }

        private object source;
        public object Source
        {
            get { return source; }
            set { source = value; }
        }

        private TransactionType type;
        public TransactionType Type
        {
            get { return type; }
            set { type = value; }
        }

        private TransactionStatus currentStatus;
        private TransactionStatus nextStatus;

        public TransactionStatus Status
        {
            get 
            {
                return currentStatus;
            }
            set 
            {
                if (nextStatus != value)
                {
                    nextStatus = value;
                    Simulator.Engine.SimulationContext.TransactionUpdateQueue.Enqueue(this);
                }
            }
        }

        private uint bytes;
        public uint Bytes
        {
            get { return bytes; }
            set { bytes = value; }
        }

        private uint address;
        public uint Address
        {
            get { return address; }
            set {
                if (value == 0x2020013 || value == 0x13000000)
                {
   //                 Console.WriteLine();
                }

                address = value; }
        }

        private uint value;
        public uint Value
        {
            get { return this.value; }
            set {
                if (value == 0x2020013 || value == 0x13000000)
                {
  //                  Console.WriteLine();
                }
                this.value = value; }
        }


        public void UpdateStatus()
        {
            currentStatus = nextStatus;
        }

        public Transaction(object source, TransactionType type, uint bytes, uint address, uint value)
        {
            this.source = source;
            this.Status = TransactionStatus.Unknown;
            this.Value = value;
            this.Address = address;
            this.type = type;
            this.bytes = bytes;


            /*
            Console.WriteLine("trans, addr: 0x{0,8:X8} value 0x{1,8:X8} type {2} {3}",
                address,
                value,
                type,
                bytes
            );
             * */
        }
    }

    public class WriteTransaction : Transaction
    {
        public WriteTransaction(object source, uint bytes, uint address, uint value)
            : base(source, TransactionType.Write, bytes, address, value)
        {
        }
    }

    public class WriteByteTransaction : WriteTransaction
    {
        public WriteByteTransaction(object source, uint address, uint value)
            : base(source, 1, address, value)
        {            
        }
    }

    public class WriteHalfWordTransaction : WriteTransaction
    {
        public WriteHalfWordTransaction(object source, uint address, uint value)
            : base(source, 2, address, value)
        {
        }
    }

    public class WriteWordTransaction : WriteTransaction
    {
        public WriteWordTransaction(object source, uint address, uint value)
            : base(source, 4, address, value)
        {
        }
    }

    public class ReadTransaction : Transaction
    {
        public ReadTransaction(object source, uint bytes, uint address)
            : base(source, TransactionType.Read, bytes, address, 0)
        {
        }
    }

    public class ReadByteTransaction : ReadTransaction
    {
        public ReadByteTransaction(object source, uint address)
            : base(source, 1, address)
        {
        }
    }

    public class ReadHalfWordTransaction : ReadTransaction
    {
        public ReadHalfWordTransaction(object source, uint address)
            : base(source, 2, address)
        {
        }
    }

    public class ReadWordTransaction : ReadTransaction
    {
        public ReadWordTransaction(object source, uint address)
            : base(source, 4, address)
        {
        }
    } 
}
